<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
namespace app\common\model\groupon;

use cores\BaseModel;
use cores\exception\BaseException;
use app\common\service\User as UserService;
use app\common\model\groupon\TaskUsers as TaskUsersModel;
use app\common\enum\groupon\TaskStatus as TaskStatusEnum;
use app\common\enum\groupon\ActiveType as ActiveTypeEnum;
use think\model\relation\BelongsTo;

/**
 * 拼团拼单模型
 * Class Task
 * @package app\common\model\groupon
 */
class Task extends BaseModel
{
    // 定义表名
    protected $name = 'groupon_task';

    // 定义主键
    protected $pk = 'task_id';

    // 定义别名
    protected string $alias = 'task';

    // 追加的字段
    protected $append = ['joined_people'];

    /**
     * 关联模型：拼团商品
     * @return BelongsTo
     */
    public function groupGoods(): BelongsTo
    {
        return $this->belongsTo('Goods');
    }

    /**
     * 关联模型：用户信息
     * @return BelongsTo
     */
    public function user(): BelongsTo
    {
        $module = self::getCalledModule();
        return $this->BelongsTo("app\\{$module}\\model\\User")->field(['user_id', 'nick_name', 'avatar_id']);
    }

    /**
     * 获取器：已拼的人数 (实际人数+模拟机器人)
     * @param $value
     * @param $item
     * @return false|string
     */
    public function getJoinedPeopleAttr($value, $item)
    {
        return $item['actual_people'] + $item['robot_people'];
    }

    /**
     * 获取器：拼单开始时间
     * @param $value
     * @return false|string
     */
    public function getStartTimeAttr($value)
    {
        return format_time($value);
    }

    /**
     * 获取器：拼单结束时间
     * @param $value
     * @return false|string
     */
    public function getEndTimeAttr($value)
    {
        return format_time($value);
    }

    /**
     * 获取拼单详情记录
     * @param int $taskId 拼单ID
     * @param array $with
     * @return static|array|null
     */
    public static function detail(int $taskId, array $with = [])
    {
        return static::get($taskId, $with);
    }

    /**
     * 获取拼单详情 (基础)
     * @param int $taskId
     * @return static|array|null
     * @throws BaseException
     */
    public static function getBasic(int $taskId)
    {
        $detail = static::detail($taskId);
        if (empty($detail) || $detail['is_delete']) {
            throwError('很抱歉，未找到该拼团');
        }
        return $detail;
    }

    /**
     * 验证当前拼单是否已完成
     * @param int $taskId 拼单ID
     * @return bool
     * @throws BaseException
     */
    public function checkTaskComplete(int $taskId): bool
    {
        $detail = static::getBasic($taskId);
        return in_array($detail['status'], [TaskStatusEnum::SUCCESS, TaskStatusEnum::FAIL]);
    }

    /**
     * 验证当前拼单是否已成功
     * @param int $taskId 拼单ID
     * @return bool
     * @throws BaseException
     */
    public function checkTaskSuccess(int $taskId): bool
    {
        $detail = static::getBasic($taskId);
        return $detail['status'] == TaskStatusEnum::SUCCESS;
    }

    /**
     * 验证当前拼单是否允许加入新成员
     * @param int $taskId 拼单ID
     * @param int|null $userId 用户ID (新成员)
     * @return bool
     * @throws BaseException
     */
    public function checkToJoinByTaskId(int $taskId, ?int $userId = null): bool
    {
        // 获取拼单详情
        $detail = static::getBasic($taskId);
        return $this->checkToJoin($detail, $userId);
    }

    /**
     * 验证当前拼单是否允许加入新成员
     * @param mixed $detail 拼单记录详情
     * @param int|null $userId 用户ID (新成员)
     * @param bool $checkIsNewUser 是否验证老带新拼团是否允许加入
     * @return bool
     */
    public function checkToJoin($detail, ?int $userId = null, bool $checkIsNewUser = true): bool
    {
        if ($detail['status'] != TaskStatusEnum::NORMAL) {
            $this->error = '当前拼单已结束';
            return false;
        }
        if (time() > $detail->getData('end_time')) {
            $this->error = '当前拼单已结束';
            return false;
        }
        if (($detail['actual_people'] + $detail['robot_people']) >= $detail['people']) {
            $this->error = '当前拼单人数已满';
            return false;
        }
        if ($userId > 0 && TaskUsersModel::isJoin($detail['task_id'], $userId)) {
            $this->error = '当前用户已参与该拼单';
            return false;
        }
        // 验证老带新拼团是否允许加入
        if ($checkIsNewUser && !$this->checkToJoinByNew($detail['active_type'], $userId)) {
            $this->error = '很抱歉，您当前不是新用户 无法参与该拼团';
            return false;
        }
        return true;
    }

    /**
     * 验证老带新拼团是否允许加入
     * @param int $activeType
     * @param int|null $userId
     * @return bool
     */
    private function checkToJoinByNew(int $activeType, ?int $userId = null): bool
    {
        return $activeType != ActiveTypeEnum::PULL_NEW || UserService::checkIsNewUser($userId);
    }
}